home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xnetbris.00 / xnetbris / server.c < prev    next >
C/C++ Source or Header  |  1995-09-19  |  14KB  |  588 lines

  1. /* 
  2.  * This is the server part of Netbrisk.
  3.     Copyright (C) 1995 Brendan Bartlett
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <signal.h>
  23. #include <unistd.h>
  24. #include <time.h>
  25. #include <string.h>
  26. #include <sys/types.h>
  27. #include <sys/time.h>
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <arpa/inet.h>
  31. #include <netdb.h>
  32.  
  33. #include "brisk.h"
  34. #include "server.h"
  35.  
  36. static int client_fd[MAX_PLAYERS];
  37. static int numplayers = MAX_PLAYERS;
  38. static int play_type;
  39.  
  40. static struct card **suits[4];
  41. static struct card **deck;
  42. static int deckp;                       /* pointer to the top of the deck */
  43. static unsigned char scores[4];         /* 0, 1 used for team, upto 4 used if chaos */
  44.  
  45. static struct card brisk;               /* the current brisk */
  46. static struct card **table;             /* the cards currently down on the table */
  47. static struct struct_hand **hand;       /* list of cards the players have */
  48.  
  49. static int sock_fd;
  50. static int start_server(unsigned short int port, int num_players);              /* returns 0 on error */
  51. static void shuffle_cards(void);
  52.  
  53. /* Brisk-playing routines */
  54. static void play_brisk(void);
  55. static int decide_winner(int, char *);              /* looks at the global table variable */
  56. static void score_table(struct packet *);
  57. static void get_card(struct card *holder, int player, int dontdeal, int tablepos);  /* gets a card from the client */
  58. static int legal_move(struct card *played, int player);                             /* returns -1 for illegal, index if ok */
  59. static int deal_card(struct struct_hand *rec_card, int player, int cardnum);
  60.  
  61. int handler(int);
  62. void main(int, char *[]);
  63.  
  64. int handler(int signum)
  65. {
  66.   fprintf(stderr, "got SIGPIPE, cleaning up\n");
  67.   
  68.   /* do cleanup here */
  69.  
  70.   exit(0);
  71.   
  72. }
  73.  
  74. void main(int argc, char *argv[])
  75. {
  76.   int port = 10000, i, j;
  77.   struct packet p;
  78.  
  79.   signal(SIGPIPE, handler);
  80.   
  81.   if(argc == 1)
  82.     {
  83.       printf("usage %s: <numplayers> <play type> <port>\n", argv[0]);
  84.       printf("   where numplayers is either 2 or 4 and play type is one of \"chaos\" or \"team\"\n");
  85.       printf("   port is optional, use only if default does not work.\n");
  86.       exit(0);
  87.     }
  88.   
  89.   numplayers = atoi(argv[1]);
  90.  
  91.   if(numplayers != 2 && numplayers != 4)
  92.     {
  93.       fprintf(stderr, "Bad argument %d, the number of players must be either 2 or 4.\n", numplayers);
  94.       exit(0);
  95.     }
  96.  
  97.   if(strcmp(argv[2], "chaos") == 0)
  98.     play_type = CHAOS;
  99.   else if(strcmp(argv[2], "team") == 0)
  100.     play_type = TEAM;
  101.   else
  102.     {
  103.       printf("Bad argument [%s], should be either \"chaos\" or \"team\"\n", argv[2]);
  104.       exit(0);
  105.     }
  106.  
  107.   if(numplayers == 2 && play_type == TEAM)
  108.     {
  109.       printf("Cannot play 2 players and team.\n");
  110.       exit(0);
  111.     }
  112.  
  113.   if(argc == 4)
  114.     port = atoi(argv[3]);
  115.  
  116.   for(i = 0; i < 4; i++)
  117.     {
  118.       scores[i] = 0;
  119.  
  120.       suits[i] = malloc(sizeof(struct card *) * CARDS_SUIT);
  121.       for(j = 0; j < CARDS_SUIT; j++)
  122.     {
  123.       suits[i][j] = malloc(sizeof(struct card));
  124.       suits[i][j]->suit = i;
  125.       suits[i][j]->weight = j + 1;
  126.     }
  127.     }
  128.  
  129.   table = malloc(sizeof(struct card *) * numplayers);
  130.   hand = malloc(sizeof(struct struct_hand *) * numplayers);
  131.  
  132.   for(i = 0; i < numplayers; i++)
  133.     {
  134.       table[i] = malloc(sizeof(struct card));
  135.       hand[i] = malloc(sizeof(struct struct_hand));
  136.     }
  137.  
  138.   shuffle_cards();
  139.  
  140.  
  141. /*
  142.   for(i = 0; i < 3; i++)
  143.     fprintf(log, "player %d: [%d %d] [%d %d] [%d %d]\n", i, hand[i]->cards[0]->suit, hand[i]->cards[0]->weight, hand[i]->cards[1]->suit, hand[i]->cards[1]->weight,  hand[i]->cards[2]->suit, hand[i]->cards[2]->weight);
  144. */
  145.  
  146.  
  147.   printf("Starting Netbrisk SERVER (Version %1.2f) on port %i, play_type %d, %d players\n", VERSION, port, play_type, numplayers);
  148.  
  149.  
  150.  
  151.   if(!start_server(port, numplayers))
  152.     {
  153.       printf("start_server failed!\n");
  154.       exit(0);
  155.     }
  156.  
  157.   /* The server has to tell the clients what cards they have by DEAL_TYPE packets */
  158.  
  159.  
  160.   for(i = 0; i < 3; i++)
  161.     for(j = 0; j < numplayers; j++)
  162.     if(!deal_card(hand[j], j, i))
  163.       printf("deal_card error!\n");
  164.  
  165.  
  166.   /* Now, after all the cards are "delt", the server selects the brisk */
  167.  
  168.   p.type = MOVE_TYPE;
  169.   p.data.move.player = 5;
  170.     
  171.   memcpy(&brisk, deck[deckp], sizeof(struct card));
  172.   memcpy(&p.data.move.play_card, &brisk, sizeof(struct card));
  173.   deckp--;
  174.  
  175.   deck[0] = &brisk;
  176.  
  177.   for(j = 0; j < numplayers; j++)
  178.     write(client_fd[j], &p, sizeof(struct packet));
  179.  
  180.   play_brisk();
  181.  
  182.   exit(0);
  183. }
  184.  
  185. static void play_brisk(void)
  186. {
  187.   int turn = 0, winner = 0, i = 0, j; /* The current players turn */
  188.   struct packet p;
  189.   char order[4];
  190.  
  191. /*  
  192.   for(tabindex = 0, turn = winner; turn < numplayers; turn = ( (turn == numplayers - 1) ? winner : (turn + 1) % numplayers), tabindex = (tabindex + 1) % numplayers)
  193. */
  194.   while(1)
  195.     {
  196.       turn = winner;
  197.  
  198.       /* no more cards on deck */
  199.       if(deckp == -1)
  200.     break;
  201.  
  202.       for(i = 0; i < numplayers; i++, turn = (turn + 1) % numplayers)
  203.     {
  204.       get_card(table[i], turn, 0, i);
  205.       order[i] = turn;
  206.     }
  207.  
  208.       winner = decide_winner(winner, order);
  209.     }
  210.  
  211.   /* play out the last hand */
  212.  
  213.   p.type = LAST_HAND;
  214.   for(i = 0; i < numplayers; i++)
  215.     write(client_fd[i], &p, sizeof(struct packet));
  216.  
  217.   for(j = 0; j < 3; j++)
  218.     {
  219.       for(i = 0, turn = winner; i < numplayers; i++, turn = (turn + 1) % numplayers)
  220.     {
  221.       get_card(table[i], turn, 1, i);
  222.       order[i] = turn;
  223.     }
  224.       winner = decide_winner(winner, order);
  225.     }
  226.  
  227.   /* game is complete */
  228.  
  229.   for(i = 0; i < numplayers; i++)
  230.     {
  231.       p.type = END_GAME;
  232.  
  233.       p.data.score.scores[0] = scores[0];
  234.       p.data.score.scores[1] = scores[1];
  235.       
  236.       write(client_fd[i], &p, sizeof(struct card));
  237.       close(client_fd[i]);
  238.     }
  239.  
  240.   printf("Game over - final score %d to %d.\n", scores[0], scores[1]);
  241. }
  242.  
  243. /* Looks at the table[] array and figures out who has won
  244.  * based on the current brisk and who went first
  245.  *
  246.  * Informs the clients of the winner.
  247.  *
  248.  * Returns the player # of the winner
  249.  */
  250. static int decide_winner(int oldwin, char *order)
  251. {
  252.   struct card *winning = table[0];
  253.   int ccheck, playerptr, winplayer = order[0], i;
  254.   struct packet out;
  255.   
  256.   for(ccheck = 1, playerptr = (oldwin + 1) % numplayers; ccheck < numplayers; ccheck++, playerptr = (playerptr + 1) % numplayers)
  257.     {
  258.       if(table[ccheck]->suit == winning->suit)
  259.     {
  260.       if(table[ccheck]->weight > winning->weight)
  261.         {
  262.           winplayer = order[ccheck];
  263.           winning = table[ccheck];
  264.         }
  265.     }
  266.       else if(table[ccheck]->suit == brisk.suit)
  267.     {
  268.       winplayer = order[ccheck];
  269.       winning = table[ccheck];
  270.     }
  271.     }
  272.   
  273.   out.type = SCORE_UPDATE;
  274.  
  275.   out.data.score.lastwin = winplayer;
  276.   
  277.   score_table(&out);
  278.  
  279.   for(ccheck = 0; ccheck < numplayers; ccheck++)
  280.       write(client_fd[ccheck], &out, sizeof(struct packet));
  281.  
  282.   for(ccheck = 0; ccheck < numplayers; ccheck++)
  283.     {
  284.       read(client_fd[ccheck], &out, sizeof(struct packet));
  285.       if(out.type != OK)
  286.     fprintf(stderr, "Client did not respond to SCORE_UPDATE correctly.\n");
  287.     }
  288.  
  289.      
  290.   return winplayer;
  291. }
  292.  
  293. /*
  294.  * This is private to decide_winner.
  295.  *
  296.  * Fills in the packet 'p' with the appropiate scores for the cards on the table
  297.  *
  298.  */
  299. static void score_table(struct packet *out)
  300. {
  301.   int cardnum, score, i;
  302.   char scoretab[] = { 0, 0, 0, 0, 0, 2, 3, 4, 10, 11 };
  303.  
  304.   for(score = 0, cardnum = 0; cardnum < numplayers; cardnum++)
  305.       score += scoretab[table[cardnum]->weight];
  306.  
  307.   if(play_type == CHAOS)
  308.     {
  309.       scores[out->data.score.lastwin] += score;
  310.  
  311.       for(i = 0; i < numplayers; i++)
  312.     out->data.score.scores[i] = scores[i];
  313.     }
  314.   else
  315.     {
  316.       unsigned char teamtab[] = { 0, 1, 0, 1 };
  317.       
  318.       scores[teamtab[out->data.score.lastwin]] += score;
  319.       
  320.       for(i = 0; i < numplayers; i++)
  321.     out->data.score.scores[teamtab[i]] = scores[teamtab[i]];
  322.     }
  323. }
  324.  
  325. /*
  326. static void print_hands(void)
  327. {
  328.   int i, j;
  329.  
  330.   for(i = 0; i < numplayers; i++)
  331.     {
  332.       printf("player %d: ", i);
  333.       for(j = 0; j < 3; j++)
  334.     printf(" %d %d", hand[i]->cards[j]->suit, hand[i]->cards[j]->weight);
  335.       printf("\n");
  336.     }
  337. }
  338. */
  339.  
  340. /*
  341.  * Gets a card from the given client.
  342.  * Checks if the card is indeed in the given players hand.
  343.  *
  344.  * Before returning, a new card is given to the client
  345.  * (in both the server data types and via a packet to the client)
  346.  * 
  347.  * Also, given that the card which the client played is legal for it to play
  348.  * (ie. is in its hand), this will inform the other clients of the card that
  349.  * this client has played (via MOVE_TYPE packets)
  350.  * 
  351.  * Returns the card that the client has played.
  352.  */
  353. static void get_card(struct card *holder, int player, int dontdeal, int tablepos)
  354. {
  355.   struct packet in, out;
  356.   int pcard = 0, i;
  357.  
  358.  
  359.   out.type = MOVE_EXPECTED;
  360.   out.data.move.player = player;
  361.  
  362.   for(i = 0; i < numplayers; i++)
  363.     if(i != player)
  364.       write(client_fd[i], &out, sizeof(struct packet));
  365.  
  366.   write(client_fd[player], &out, sizeof(struct packet));
  367.   
  368.   /* Now, we wait for the client to send back a card */
  369.   read(client_fd[player], &in, sizeof(struct packet));
  370.  
  371.   /* If the client send a bogus card, loop until it gives a card in its hand */
  372.  
  373.   if((pcard = legal_move(&in.data.move.play_card, player)) == -1)
  374.     do
  375.       {
  376.     out.type = ILLEGAL_MOVE;
  377.     write(client_fd[player], &out, sizeof(struct packet));        
  378.         
  379.     read(client_fd[player], &in, sizeof(struct packet));
  380.       }
  381.     while( (pcard = legal_move(&in.data.move.play_card, player)) == -1);
  382.  
  383.  
  384.   out.type = OK;
  385.   out.data.ok.cardpos = pcard;
  386.   write(client_fd[player], &out, sizeof(struct packet));
  387.  
  388.   /* save the played card into the given pointer */
  389.   memcpy(holder, &in.data.move.play_card, sizeof(struct card));
  390.  
  391.   /* Deal out a new card to the player */
  392.  
  393.   if(! dontdeal)
  394.     deal_card(hand[player], player, pcard);
  395.  
  396.   in.data.move.tablepos = tablepos;
  397.  
  398.   /* Inform the clients of the card which the other client has played */
  399.  
  400.   for(i = 0; i < numplayers; i++)
  401.     write(client_fd[i], &in, sizeof(struct packet));
  402.   
  403.   return;
  404. }
  405.  
  406. /*
  407.  * This function will only tell if the 'played' card is inside the hand of the
  408.  * player who played the card
  409.  *
  410.  * Returns the card (in the server data types) the client played.
  411.  * or -1 for no such card (illegal move)
  412.  */
  413. static int legal_move(struct card *played, int player)
  414. {
  415.   int i, rtn = -1;
  416.  
  417.   for(i = 0; i < 3; i++)
  418.       if(played->suit == hand[player]->cards[i]->suit && played->weight == hand[player]->cards[i]->weight)
  419.     rtn = i;
  420.   
  421.   return rtn;
  422. }
  423.  
  424.  
  425. void shuffle_cards(void)
  426. {
  427.   int shuffle[NUM_CARDS + 1], flag[NUM_CARDS + 1];
  428.   int i;
  429.  
  430.  
  431.   deck = malloc(sizeof(struct card *) * NUM_CARDS + 1);
  432.   for(i = 0; i < NUM_CARDS + 1; i++)
  433.     deck[i] = malloc(sizeof(struct card));
  434.  
  435.   srand(time(NULL));
  436.  
  437.   memset(flag, 0, sizeof(int) * (NUM_CARDS + 1));
  438.  
  439.   for (i=0; i != 40; i++)
  440.     {
  441.       while(1)
  442.     {
  443.       shuffle[i]=rand() % 40;
  444.       if (flag[shuffle[i]] == 0)
  445.         {
  446.           flag[shuffle[i]] = 1;
  447.           break;
  448.         }
  449.     }
  450.     }
  451.  
  452.   for(i = 0; i < 40; i++)
  453.     if(shuffle[i] < 10)
  454.       {
  455.     deck[i+1]->suit = SUN;
  456.     deck[i+1]->weight = shuffle[i];
  457.       }
  458.     else if(shuffle[i] < 20)
  459.       {
  460.     deck[i+1]->suit = SWORD;
  461.     deck[i+1]->weight = shuffle[i] - 10;
  462.       }
  463.     else if(shuffle[i] < 30)
  464.       {
  465.     deck[i+1]->suit = BONE;
  466.     deck[i+1]->weight = shuffle[i] - 20;
  467.       }
  468.     else
  469.       {
  470.     deck[i+1]->suit = CUP;
  471.     deck[i+1]->weight = shuffle[i] - 30;
  472.       }
  473.  
  474.   /* set up the pointer to the top of the deck array */
  475.  
  476.   deckp = NUM_CARDS; 
  477.  
  478. }
  479.  
  480. /* This routine takes a player number and a structure and deals this player
  481.  * a new card.
  482.  * 
  483.  * Returns 0 on failure, 1 for success
  484.  */
  485.  
  486. static int deal_card(struct struct_hand *rec_card, int player, int cardnum)
  487. {
  488.   struct packet p;
  489.  
  490.   if(cardnum < 0 || cardnum > 3)
  491.     return 0;
  492.  
  493.   rec_card->cards[cardnum] = deck[deckp];
  494.     
  495.   p.type = DEAL_TYPE;
  496.   p.data.deal.rec_place = cardnum;
  497.  
  498.  
  499.   memcpy(&p.data.deal.deal_card, rec_card->cards[cardnum], sizeof(struct card));
  500.   write(client_fd[player], &p, sizeof(struct packet));
  501.  
  502.   deckp--;
  503.   return 1;
  504. }
  505.       
  506.       
  507.   
  508. int start_server(unsigned short int port, int num_players)
  509. {
  510.   int optval, namelen;
  511.   struct sockaddr_in addr;
  512.   struct protoent *proto;
  513.   int player_count;
  514.   struct packet p;
  515.  
  516.  
  517.   p.type = INFORM_TYPE;
  518.  
  519.   p.data.inform.numplayers = numplayers;
  520.   p.data.inform.play_type = play_type;
  521.  
  522.   proto = getprotobyname("tcp");
  523.  
  524.   if(proto == 0)
  525.     {
  526.       fprintf(stderr, "tcp not supported here!\n");
  527.       return 0;
  528.     }
  529.  
  530.   addr.sin_family = AF_INET;
  531.   addr.sin_port = htons(port);
  532.   addr.sin_addr.s_addr = htonl(INADDR_ANY);
  533.   sock_fd = socket(AF_INET, SOCK_STREAM, proto->p_proto);
  534.   
  535.   if(sock_fd == -1)
  536.     {
  537.       fprintf(stderr, "cannot open socket!\n");
  538.       return 0;
  539.     }
  540.      
  541.   /* allow the local port to be re-used by the server over and over */
  542.   if(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) == -1)
  543.      {
  544.        perror("setsockopt");
  545.        return 0;        /* not reached */
  546.      }
  547.   
  548.   if(bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
  549.     {
  550.       perror("bind");
  551.       return 0; 
  552.     }
  553.      
  554.   if(listen(sock_fd, 1) == -1)
  555.     {
  556.       perror("listen");
  557.       return 0;      
  558.     }
  559.  
  560.   for(player_count = 0; player_count < num_players; player_count++)
  561.     {
  562.       printf("Waiting for player %d to connect to port %i.\n", player_count+1, port);
  563.       client_fd[player_count] = accept(sock_fd, (struct sockaddr *)&addr, &namelen);
  564. /*
  565.       write(client_fd[player_count], VERSION, strlen(VERSION));
  566. */
  567.       p.data.inform.yournumber = player_count;
  568.  
  569.       write(client_fd[player_count], &p, sizeof(struct packet));
  570.  
  571.     }
  572.   
  573.   close(sock_fd);
  574.  
  575.   return 1;
  576. }
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.